/*
 * Created on Mar 10, 2005
 *
 * TODO To change the template for this generated file go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
package bmoofxbridge;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import net.ofx.types.x2003.x04.OFXDocument;

import org.apache.xmlbeans.XmlException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.develop.jawin.COMException;

import bmoofxbridge.model.Model;
import il.co.fibi.bmo.BMOLib._DBMO;

/**
 * @author leonidr
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 */
public class DataProcessor {
	private _DBMO BMOcx;
	private Model model = new Model();
	private BMOParser parser;
	

	/**
	 * @param ocx
	 */
	public DataProcessor(_DBMO ocx) {
		super();
		BMOcx = ocx;
	}
	
	public boolean loginToBMO(){
		return true;
	}
	
	public void extractData() throws COMException{
		parser = new BMOParser(BMOcx);
		parser.fillModel(model);
	}
	
	public Document getReport(Document request) throws COMException{
		org.w3c.dom.ProcessingInstruction pi = null;
		
		OFXDocument ofxRequest = null;
		try {
			if (request!=null){
				NodeList docChildren = request.getChildNodes();
				for (int i = 0; i < docChildren .getLength(); i++) {
					Node node = docChildren.item(i);
					if (node instanceof org.w3c.dom.ProcessingInstruction)
						pi = (ProcessingInstruction) node;
				}
				
				
				ofxRequest = OFXDocument.Factory.parse(request);
			}
		} catch (XmlException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		OFXDocument doc = parser.getFullStatement(model, ofxRequest);
		Document docDomNode = (Document) doc.newDomNode();
		Element ofxDomElement = docDomNode.getDocumentElement();
		ofxDomElement.setPrefix(null);
		ofxDomElement.removeAttribute("xmlns");
		ofxDomElement.removeAttribute("xmlns:ns");

		Document newDoc = docDomNode.getImplementation().createDocument(null,
				"OFX", null);
		if (pi==null)
		{
			pi = newDoc
				.createProcessingInstruction(
						"OFX",
						"OFXHEADER=\"200\" VERSION=\"200\" SECURITY=\"NONE\" OLDFILEUID=\"NONE\" NEWFILEUID=\"NONE\"?");
			newDoc.insertBefore(pi, newDoc.getDocumentElement());
		}
		else{
			pi = newDoc
			.createProcessingInstruction(
					"OFX",
					pi.getData()+"?");
			newDoc.insertBefore(pi, newDoc.getDocumentElement());

			
//			newDoc.insertBefore(newDoc.importNode(pi, true), newDoc.getDocumentElement());
		}

		Element newOfxDomElement = newDoc.getDocumentElement();
		NodeList children = ofxDomElement.getChildNodes();

		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			newOfxDomElement.appendChild(newDoc.importNode(node, true));
		}

		return newDoc;
	}
	
	public void saveReport(Document report, String fileName){
			OutputStream os;
			try {
				os = new FileOutputStream(fileName);
				PrintStream ps = new PrintStream(os);
				printDocument(report, ps);				
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
	}
	
	public void saveReport(Document report, OutputStream os){
		PrintStream ps = new PrintStream(os);
		printDocument(report, ps);				
	}

	public OFXDocument parseRequest(InputStream is){
		try {
			OFXDocument result = OFXDocument.Factory.parse(is);
			return result;
		} catch (XmlException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;		
	}
	
	
	public Document parseRequestStream(InputStream is){
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.parse(is);
			
			Element ofxDomElement = document.getDocumentElement();
			ofxDomElement.setPrefix("ns");
			ofxDomElement.setAttribute("xmlns","http://ofx.net/types/2003/04");
			ofxDomElement.setAttribute("xmlns:ns","http://ofx.net/types/2003/04");

//			;
			return document;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;		
	}
	
	public Document parseRequestReader(Reader reader){
		try {
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			InputSource src = new InputSource(reader);
			Document document = builder.parse(src);
			Element ofxDomElement = document.getDocumentElement();
			
			Document newDoc = document.getImplementation().createDocument("http://ofx.net/types/2003/04",
					"OFX", null);
			
			NodeList docChildren = document.getChildNodes();
			for (int i = 0; i < docChildren .getLength(); i++) {
				Node node = docChildren .item(i);
				if (node!=ofxDomElement)
					newDoc.appendChild(newDoc.importNode(node, true));
			}
			

			
			Element newOfxDomElement = newDoc.getDocumentElement();
			NodeList children = ofxDomElement.getChildNodes();

			for (int i = 0; i < children.getLength(); i++) {
				Node node = children.item(i);
				newOfxDomElement.appendChild(newDoc.importNode(node, true));
			}
			
			
			//ofxDomElement.setAttribute("xmlns","http://ofx.net/types/2003/04");
			//ofxDomElement.setAttribute("xmlns:ns","http://ofx.net/types/2003/04");
//			ofxDomElement.setNodeValue(XML_PRINT_TRANSFORMER)
//			ofxDomElement.setPrefix("ns");

			return newDoc;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;		
	}

	
	public static final String XML_PRINT_TRANSFORMER = "<?xml version=\"1.0\"?>"
		+ "<xsl:stylesheet "
		+ "xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" version=\"1.0\" "
		+ "xmlns:xalan=\"http://xml.apache.org/xslt\" "
		+ "exclude-result-prefixes=\"#default,xmlns,ns\" "
		+ ">"
		+ "<xsl:output method=\"html\" indent=\"yes\" xalan:indent-amount=\"3\"/>"
		+ "<xsl:strip-space elements=\"*\" />"
		+ "<xsl:template match=\"/\">"
		+ "<xsl:text disable-output-escaping=\"yes\">&lt;?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?&gt;\n</xsl:text>"
		+ "<xsl:apply-templates/>"
		+ "</xsl:template>"
		+ "<xsl:template match=\"@*|comment()|processing-instruction()|text()|*\">"
		+ " <xsl:copy>"
		+ " <xsl:apply-templates select=\"@*|comment()|processing-instruction()|text()|*\"/>"
		+ " </xsl:copy>" + "</xsl:template>" + "</xsl:stylesheet>";

/**
 * Serialize a Document to a PrintStream
 *
 * @param aDocument The document to save
 * @param aOut The output stream
 */
static void printDocument(Document aDocument, PrintStream aOut) {
	try {
		TransformerFactory tfactory = TransformerFactory.newInstance();
		Element tempElement = aDocument.getDocumentElement();
		StringReader xslReader = new StringReader(XML_PRINT_TRANSFORMER);
		Templates template = tfactory.newTemplates(new StreamSource(
				xslReader));
		Transformer serializer = template.newTransformer();
		serializer.transform(new DOMSource(aDocument), new StreamResult(
				aOut));
	} catch (Exception e) {
		System.err.println("Exception from XML serializing: "
				+ e.toString());
		e.printStackTrace(System.err);
	}
}
}
